/* SPDX-License-Identifier: GPL-2.0 */
#ifndef SEMINIX_SMP_H
#define SEMINIX_SMP_H

#include <seminix/list.h>
#include <seminix/llist.h>
#include <seminix/cpumask.h>
#include <asm/smp.h>

struct task_struct;

#define smp_processor_id() raw_smp_processor_id()

#define get_cpu()		({ preempt_disable(); smp_processor_id(); })
#define put_cpu()		preempt_enable()

typedef void (*smp_call_func_t)(void *info);
struct __call_single_data {
    struct llist_node llist;
    smp_call_func_t func;
    void *info;
    unsigned int flags;
};

/* Use __aligned() to avoid to use 2 cache lines for 1 csd */
typedef struct __call_single_data call_single_data_t
    __aligned(sizeof(struct __call_single_data));

int smp_call_function_single(int cpuid, smp_call_func_t func, void *info,
                 int wait);
int smp_call_function_single_async(int cpu, call_single_data_t *csd);

/*
 * Call a function on all other processors
 */
int smp_call_function(smp_call_func_t func, void *info, int wait);
void smp_call_function_many(const struct cpumask *mask,
                smp_call_func_t func, void *info, bool wait);
int smp_call_function_any(const struct cpumask *mask,
              smp_call_func_t func, void *info, int wait);

/*
 * Call a function on all processors
 */
int on_each_cpu(smp_call_func_t func, void *info, int wait);

/*
 * Call a function on processors specified by mask, which might include
 * the local one.
 */
void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
        void *info, bool wait);

extern void kick_all_cpus_sync(void);

extern struct task_struct *idle_task_init_once(int cpu);

extern void setup_nr_cpu_ids(void);
extern void smp_init(void);
extern void smp_setup_processor_id(void);
/*
 * Mark the boot cpu "online" so that it can call console drivers in
 * printk() and can access its per-cpu storage.
 */
extern void smp_prepare_boot_cpu(void);

/*
 * Generic and arch helpers
 */
void call_function_init(void);
void generic_smp_call_function_single_interrupt(void);
#define generic_smp_call_function_interrupt \
    generic_smp_call_function_single_interrupt

#endif /* !SEMINIX_SMP_H */
